home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
chasm.dqc
/
CHASM.DOC
Wrap
Text File
|
1984-06-14
|
106KB
|
4,423 lines
READ
THIS
BEFORE
PRINTING!!!!
This document has been formatted in a special way. Virtually all dot
matrix printers have a condensed mode which prints 132 characters
across a standard 8 1/2 inch page. When this file is printed out in
condensed mode, the resulting printed pages can be cut down to 5 1/2 X
8 1/2 inches. The cut pages will fit nicely in the back of your
DOS manual for storage.
Typically, you can turn on this mode by sending a special control
sequence to the printer from BASIC. For example, you can turn on the
condensed mode of the IBM/Epson printer with the BASIC statement:
LPRINT chr$(15). If your printer has such a condensed mode, turn it
on now, before printing the rest of this document.
(tm)
CHASM
Cheap Assembler
for the IBM Personal Computer
User's Manual
(c) 1983 by David Whitman
Versions 2.13/3.14
David Whitman
136 Wellington Terrace
Lansdale, PA 19446
(215) 641-7114 (days)
(215) 362-8526 (evenings)
Table of Contents
Why CHASM?..................................................1
What can CHASM do?..........................................2
What WON'T it do?...........................................2
The Two Versions of CHASM...................................3
Setting Up a CHASM Work Disk................................4
Modifying CHASM's I/O Defaults..............................6
Syntax......................................................9
Labels.....................................................11
Operands...................................................14
Resolution of Ambiguities..................................19
Pseudo-Operations..........................................22
Structures.................................................28
Outside the Program Segment................................32
Running CHASM..............................................33
Error and Diagnostic Messages..............................36
Execution of Assembled Programs............................40
Notes for Those Upgrading to This Version of CHASM.........44
Miscellaneous and A Word From Our Sponsor..................47
Appendix A: Mnemonic List..................................51
Appendix B: Differences Between CHASM and TOA..............53
Appendix C: Description of Files...........................59
Compiled Version Order Form................................60
1
>>Why CHASM?<<
Why go to the trouble to write an assembler, when one already
exists? The IBM Macro Assembler is a very powerful software tool
available off the shelf. It supports features such as macros,
multiple segments, and linking to external procedures.
Unfortunately, the cost of all this power is complexity. The
macro assembler is so complicated that IBM warns beginners it is
only suitable for "experienced assembly language programmers".
For most users, this sophistication is more of a hindrance than
an aid. Even when writing short, simple programs, the user is
saddled with a set of confusing pseudo-ops only appropriate for
large, multi-segment programs. Producing a fast loading
executable file requires running three separate programs (MASM,
LINK and EXE2BIN) before you can get down to testing.
The macro assembler is totally unsuitable for use with BASIC.
Although it is *possible* to produce machine language subroutines
for BASIC with the macro assembler, the process is incredibly
convoluted and confusing.
To top it all off, the macro assembler costs an overpriced $100.
CHASM is, I hope, a more reasonable compromise between power and
accessibility. CHASM is simple to use and understand. Unlike
the macro assembler, CHASM doesn't require a second LINK step to
produce a working program. CHASM also produces fast loading
programs without the use of the utility EXE2BIN.
CHASM supports two different, simple mechanisms for getting
machine language routines into BASIC, the most popular language
for the IBM Personal Computer.
Finally, the suggested donation for CHASM is a modest $30.
A Note for Beginners:
Before going on, you might find it useful to print and read the
file PRIMER.DOC, included on your CHASM disk. PRIMER is a gentle
introduction to assembly language, which will teach you some of
the vocabulary and key concepts you will need to start out with.
2
>>What can CHASM do?<<
CHASM takes a text file, consisting of mnemonics, user-defined
symbols, numbers, and pseudo-ops, and produces a file of
corresponding machine language for the 8088 processor. CHASM
allows you to define labels for branching, rather than requiring
you to figure out offsets or addresses to jump to. It allows you
to represent with a name any constants you want to use, making
your programs easier to understand. Most importantly, it
translates assembly language mnemonics to their machine language
equivalents freeing you from the task of hand translation.
>>What WON'T it do?<<
In the interest of simplicity, CHASM has a number of
restrictions:
1. Macros are not supported.
2. Arithmetic expressions within operand lists are not supported,
at least in the current release.
3. Multiple segment definitions are not allowed. CHASM assumes
that your entire program fits in one segment, that the cs, ds,
and es registers all point to this same segment, and that the
ss register points to a valid stack area. An equivalent
statement is that CHASM produces COM files, not EXE files.
4. Linking is not supported. Programs produced by CHASM must
either be stand-alone units, or subroutines called from BASIC
programs (either interpreted or compiled). You can't use
CHASM to produce object modules to link into Pascal or FORTRAN
programs.
3
>>The Two Versions of CHASM<<
CHASM is available in two flavors, interpreted and compiled.
You can tell which version you have by listing the directory of
you CHASM disk. If the file CHASM.EXE is present, you have the
compiled version, otherwise you have the interpreted version.
The interpreted version is the "budget" release. It's much
slower, and doesn't support all the advanced features of the
compiled version. The advantages of the interpreted version are
that it is available for free trial under the Freeware (tm)
plan, and requires only 64K to run.
The compiled version is the "deluxe" release. It clocks in about
six times faster, and supports a number of bells and whistles not
offered in the interpreted version. This version of CHASM
requires 128K to run, and is only available to those who support
CHASM's development by sending a payment of $30 or more. An
order form for the compiled version is included at the end of
this document.
Throughout this document, advanced features supported only by the
compiled version will be marked as follows:
==>Compiled version only.
Attempts to use these features in the interpreted version will
generally result in error messages, with the advanced feature
otherwise being ignored; however, unpredictable behavior could
result in some instances.
4
>>SETTING UP A CHASM WORK DISK<<
CHASM comes in two flavors: interpreted and compiled. You can
tell which version you have by listing the directory of your
CHASM distribution disk. If the file CHASM.EXE is present, you
have the compiled version. If not, you have the interpreted
version. Follow the appropriate instructions below to make a
CHASM work disk:
Compiled version:
Format a fresh diskette with the /S option (to include DOS). Now
copy the following files from your CHASM distribution disk:
CHASM.EXE
CHASM128.DAT
Interpreted version:
Format a fresh diskette with the /S option (to include DOS). From
your master DOS diskette, copy the file:
BASIC.COM
Now copy the following files from your CHASM distribution disk:
CHASM.BAT
CHASM.BAS
CHASM.DAT
5
Both versions:
The file CLEAR.ASM on your CHASM distribution disk is provided as
a sample assembly language source file. If you want to try out
CHASM before writing a source program of your own, copy CLEAR.ASM
onto your work disk.
If you wish to change any of CHASM's assumptions about your
printer or monitor, you should include a CHASM.CFG file on your
work disk. See the section titled "Modifying CHASM's I/O
Defaults" for a discussion of the CHASM.CFG file.
You may find it convenient to keep a copy of your text editor
(EDLIN, VEDIT, etc.) on your work diskette, for creation and
modification of source files.
If you plan to incorporate machine language routines in BASIC
programs, copy the utility program COM2DATA (file COM2DATA.EXE or
COM2DATA.BAS) from your CHASM distribution disk.
DOS 2.0 users: a high speed, DOS 2.0 filter version of COM2DATA
is now available. Check your disk for the file COM2DATA.ASM and
assemble it with CHASM before use.
6
>>MODIFYING CHASM'S I/O DEFAULTS<<
CHASM supports the use of a configuration file, which can be used
to override some of CHASM's default assumptions about your printer
and video monitor. If you are willing to accept CHASM's
defaults, you may skip this section - CHASM will work perfectly
well without the file described below.
The configuration process involves supplying a file named
CHASM.CFG on your work disk. The file should contain a series of
text "switches" of the following form:
/SWITCH, nn [, mm, oo,...]
Where "/SWITCH" is a reserved word, listed below, and nn, mm, oo
are numbers. The reserved word must be in all caps. The
brackets around mm and oo indicate that these numbers are
optional - don't put brackets in CHASM.CFG. Each number or word
should be separated by a comma or should start a new line.
The following switches are implemented:
/132 Printer 132 column mode. The numbers following this
switch are the ASCII codes for the characters which
cause your printer to go into condensed mode. You
may specify as many characters as you like. If you
don't provide this switch, CHASM will truncate source
lines in listings to avoid going over 80 columns.
You can also include characters to activate any other
special features of your printer you want CHASM to
turn on before printing. Example: (for IBM printer)
/132, 15
/80 Printer 80 column mode. Similar to /132, but the
numbers represent the characters to return your
printer to normal. Include the codes for any
characters you want CHASM to send to your printer
before returning you to DOS. The following example
turns off condensed mode and causes a form feed on
the IBM printer:
/80, 18, 12
7
/BEEP Enables/Disables audible warning when errors are
discovered in your source program. A value of zero
turns off beeping, anything else turns it on.
Example: (off)
/BEEP, 0
/FG Foreground color. Users with color monitors may
select a foreground color from the following list:
0 Black 8 Gray
1 Blue 9 Light Blue
2 Green 10 Light Green
3 Cyan 11 Light Cyan
4 Red 12 Light Red
5 Magenta 13 Light Magenta
6 Brown 14 Yellow
7 White 15 High Intensity White
Example: (Magenta)
/FG, 5
/BG Background color. Selections 0-7 above are
available. Example: (Cyan)
/BG, 3
/PAGELEN CHASM assumes that there are 66 lines to each
printed page. If you use different sized paper,
enter the number of lines per page after this switch.
Example: (European standard)
/PAGELEN, 72
/LINES By default, CHASM will print 58 lines on each printed
page, then skip over the perforation to the next
page. You can change this number to suit your paper
and personal taste. Example:
/LINES, 50
8
A sample CHASM.CFG file, suitable for use with the IBM dot matrix
printer, is included on your CHASM distribution disk.
Note for users of Jim Button's PC-FILE (tm):
CHASM.CFG has the same format as PC-FILE's PRT.CTL file,
except that the /40 switch is not implemented. If you have
already written a special PRT.CTL file, just make a copy named
CHASM.CFG for use with CHASM.
9
>>Syntax<<
CHASM accepts a standard DOS text file for input. Lines may be
any combination of upper and lower case characters. CHASM does
not distinguish between the two cases: everything except single
quoted strings are automatically converted to upper case during
the parsing process. Thus, BUFFER, Buffer, buffer, and bUFFer
all refer to the same symbol.
The characters blank ( ), comma (,), single quote (')
semi-colon (;) and TAB are reserved, and have special meaning to
CHASM (see below).
Each line must be no more than 80 characters long and have the
following format:
Label Operation Operand(s) ;comment
The different fields of an input line are separated by the
delimiters blank ( ), comma (,) or TAB. Any number of any
delimiter may be used to separate fields.
Explanation of Fields:
Label: A label is a string of characters, beginning in column 1.
Depending on the operation field, the label might represent a
program location for branching, a memory location, or a
numeric constant (see the section titled "Labels" for more on
this topic). To ensure that CHASM can distinguish between
labels and numeric constants, the first character of a label
must *not* be a number (0-9), plus sign (+) or minus sign(-).
Anything beginning in column 1, except a comment, is
considered a label.
Operation: Either a pseudo-op (see the section with the same
name) or an instruction mnemonic as defined in "The 8086
Book" by Rector and Alexy. A list of acceptable mnemonics is
given in Appendix A.
Note 1: Except as modified below,"The 8086 Book" is the
definitive reference for use with CHASM.
Note 2: There are several ways to resolve some ambiguities in
8086 assembly language. Please read page 3-285 of The 8086
Book, and "Resolution of Ambiquities" in this document.
10
Operand(s): A list of one or more operands, as defined in
the section titled "Operands", separated by delimiters.
Comment: Any string of characters, beginning with a semicolon
(;). Anything to the right of a semicolon will be ignored by
CHASM.
Note that except for the case of an operation which requires
operands, or the EQU pseudo-op which requires a label, all of the
fields are optional. The fields MUST appear in the order shown.
11
>>Labels<<
The symbol in the label field of an input line can be interpreted
in three different ways by CHASM:
1. A program location which may be branched to.
2. A memory location for data storage.
3. An equated symbol, which takes the place of a numeric
constant.
The default interpretation of a symbol is a program location for
branching. This default is modified by the presence of one of
the following pseudo-ops in the instruction field:
DB, DM, DS, or DW:
Normal: The symbol is a memory location.
In a Structure: The symbol is a numeric constant.
EQU:
Normal: The symbol is a numeric constant.
Memory Option: The symbol is a memory location.
A given symbol may have only ONE of the above interpretations!
Attempts to branch into a memory location or an equated symbol
will result in error messages. Similarly, CHASM will not allow
you to treat program code as a data area. Examples:
TEXT DB 'Hit any key when ready' ;memory location
MOV AL,TEXT ;ok
JMP TEXT ;wrong!
LOOP MOV AX,CX ;program location
JMP LOOP ;ok
MOV AX, LOOP ;wrong!
12
If for some arcane reason you *need* to branch into a data area,
you can fool CHASM by placing a label on an otherwise blank line,
immediately before the data area. Example:
JNZ NPU
RET
NPU ;dummy label for jump
DB D8H, 00H ;an 8087 instruction
If you have a masocistic urge to crash your system by writing
self-modifying code, there are at least two ways you can defeat
CHASM's injunction against using program code as a data area.
The first way is to use DS to declare zero bytes of storage
immediately before the code you want to access. A label on the
null DS will have the same offset as the immediately following
code. Example:
MOV JUNK1, 9090 ;change endless loop to NOP
JUNK1 DS 0
JUNK JMP JUNK
A sneakier approach is to load the OFFSET of a program
location into a register, then use the register for indirect
addressing. Using the optional displacement field, you can even
address the middle of an instruction. Examples:
MOV BX, OFFSET(CALL)
MOVB 1[BX], 00H ;change interrupt number in code
CALL INT 0
In general, I cannot recommend trying to get around CHASM's type
restrictions. If you find yourself in a situation where it
seems necessary to fool CHASM, there's probably a safer, more
direct way to legally program what you're trying to accomplish.
13
To avoid ambiguity, a given string can legally appear in the
label field of only ONE statement. If the same string appears on
more than one instruction, all instances after the first will
receive an error message.
TWO EQU '2' ;first use is ok
TWO PROC FAR ;wrong! symbol already defined
CHASM has a number of reserved strings which are "predefined" in
the symbol table, and will generate an error message if used as
labels. All the two letter register names are reserved, as are
the indirect address mode combinations. The only other reserved
strings are the words "NEAR" and "FAR". Examples:
AX MOV AX, DX ;wrong! (register name)
[DI] ADD AX, BX ;wrong! (indirect address)
FAR CALL GETINPUT ;wrong! (reserved word)
14
>>Operands<<
The following operand types are allowed.
1. Immediate data: A number, stored as part of the program's
object code. Immediate data are classified as either byte,
expressible as an 8 bit binary integer; or word, expressible
as a 16 bit binary integer. If context requires it, CHASM
will left-pad byte values with zeroes to convert them to word
values. Attempts to use a word value where only a byte will
fit will cause an error message to be printed.
Immediate data may be represented in 9 ways:
A. An optionally signed decimal number in the range -32768
to 32767. Examples:
MOV AL,21
MOV BX,-6300
B. A series of up to 4 hex digits, followed by the letter
H. The first digit must be non-alphabetic, i.e. in the
range 0-9, to allow CHASM to distinguish between numbers
and symbols. If necessary, a leading zero, which does
not count in the four allowed digits, may be added to
fulfill the non-alphabetic condition. Examples:
ADD CX, 0B123H
ADD DL, 12H
C. ==>Compiled version only.
A series of up to 16 binary digits, followed by the
letter B. Examples:
MASK EQU 00000111B
MOV AL, 10000000B
D. A symbol representing types A, B or C above,
defined using the EQU pseudo-op. Examples:
MASK EQU 10H
MAX EQU 1000
AND CL,MASK
SUB AX,MAX
15
E. The offset of a label or storage location returned by
the OFFSET operator. OFFSET always returns a word
value. OFFSET is used to get the address of a named
memory location, rather than its contents. Example:
MOV DI,OFFSET(BUFFER)
BUFFER DS 0FFH
F. The ASCII value of a printable character, represented by
the character enclosed in single quotes ('). Thus, the
following lines will generate the same object code:
MOV AL,41H ;ascii code for 'A'
MOV AL,'A'
G. ==>Compiled version only:
Labels within structures become immediate operands whose
values equal their offset within the structure. See the
section titled "Structures" for more detail and
examples.
H. ==>Compiled version only:
The length of a structure, returned either by the LENGTH
operator, or simply the structure's name. See the
section titled "Structures" for more detail and
examples.
I. ==>Compiled version only:
The number of bytes counted by the COUNT pseudo-op,
returned by the LENGTH operator on the COUNT's label.
Example:
HLP_MSG COUNT
HLP_TXT DB 'Hit F10 for Help...' cr lf
ENDC
MOV CX, LENGTH(HLP_MSG) ;length of message
16
2. Register Operands: One of the 8088's internal registers.
A. An 8 bit register from the following list:
AH AL
BH BL
CH CL
DH DL
B. A 16 bit register from the following list:
AX BX CX DX SP BP SI DI
C. A segment register from the following list:
CS SS DS ES
3. Memory Operands: The contents of a memory location addressed
by one of the following methods. Note that none of the memory
addressing options specifies whether a byte or word operand
is being referenced. See the section titled "Resolution of
Ambiguities" for more on this topic.
A. Direct address.
1. A number, or symbol representing a number, enclosed in
brackets, indicating an offset into the data segment.
Example:
BUFFER EQU 5A5AH
MOV BH,[BUFFER]
MOV [80H],DI
2. A symbol, defined to be a variable (i.e. a named memory
location) using the EQU pseudo-op. Example:
FCB EQU [80H]
MOV DI,FCB
3. A symbol, defined to be a variable by its use on a
storage defining pseudo-op. Examples:
MOV AX,FLAG
MOV DATE,BX
FLAG DS 1
DATE DB 31
17
B. Indirect Address: The address of the operand is the
sum of the contents of the indicated register(s) and a
displacement. The register, or sum of registers, are
enclosed in square brackets: []
The displacement is optional, and takes the form of an
immediate operand, placed without intervening delimiters to
the left of the first bracket. Displacements in the range
-128 to 127 (i.e. hex 0 - 7F, FF80 - FFFF) are interpreted
as signed 8 bit quantities. All other displacements are
interpreted as unsigned 16 bit quantities. (Note that
although the 8088 supports unsigned 16 bit displacements up
to hex FFFF for indirect addressing, CHASM isn't smart
enough to distinguish between -1 and FFFFH.)
The following indirect modes are allowed:
1. Indirect through a base register (BX or BP). Examples:
ENTRYLENGTH EQU 6
MOV AX, ENTRYLENGTH[BP]
MOV DL, -2[BX]
MOV CX, [BP]
MOV 9A9AH[BX], AX
2. Indirect through an index register (DI or SI).
Examples:
MOV [DI], CX
MOV CX, -5[SI]
3. Indirect through the sum of one base register and one
index register. Examples:
MOV [BP+DI], SP ;note that no spaces are
MOV BX, 10H[BX+SI] ;allowed within the
MOV CL, [BP+SI] ;brackets.
MOV DH, -2[BX+DI]
18
4. Labels
A label on most instructions may be used as an operand for
call and jump instructions. See the section titled "Labels"
for more information. Examples:
START PROC NEAR
CALL GETINPUT
JMPS START
ENDP
GETINPUT PROC NEAR
5. Strings
A string is any sequence of characters (including delimiters)
surrounded by single quotes ('). Example:
DB 'Copyright May 15,1982'
19
>>Resolution of Ambiguities<<
The language defined in "The 8086 Book" contains a number of
ambiguities which must be resolved by an assembler. This is
discussed throughout the book, but pages 3-285 and 3-286
specifically cover this topic. CHASM's solutions of these
problems are discussed in this section.
A. Memory references:
When one specifies the address of a memory location, it is
unclear how large an operand is being referenced. An operand
might be a byte, or a word.
1. If a register is present as an operand, it is assumed that
the memory operand matches the register in size. An
exception to this rule are the shift and rotate
instructions, where the CL register is used as a counter,
and has nothing to do with the size of the other operand.
Examples:
MOV MASK,AX ;mask is a word
MOV DH,[BX] ;BX points to a byte
NEG [SI] ;error, operand of unknown size
SHR FLAG,CL ;error, flag is of unknown size
2. If no register is present, (or if the only register is CL
being used as a counter) the size of the memory operand is
specified by adding the suffix "B" or "W" to the
instruction mnemonic. Examples:
NEGB [SI] ;SI points to a byte
SHRW FLAG,CL ;flag is a word
MOVW MASK,0AH ;mask is a word
MOVB MASK,0AH ;mask is a byte
MOVW MASK,9A9AH ;must specify size even though
;immediate operand implies word
MOVB DH,[BX] ;error(!), register already
;specifies size
20
B. Indirect Branching.
The 8088 supports two flavors of indirect branching: intra, and
intersegment. A register is set to point at a memory location
which contains a new value for the program counter, and in the
case of intersegment branching, a new value for the CS register
as well.
The syntax of "The 8086 Book" does not specify which flavor of
branch is being invoked. CHASM adds the suffixes "N" (for near,
or intrasegment) and "F" (for far, or intersegment) to the
indirect CALL and JMP mnemonics. Examples:
CALLN [BX] ;intrasegment call
JMPF [DI] ;intersegment jump
JMP [BP] ;error, unspecified flavor
C. Long and Short Jumps
Two types of relative jumps are supported by the 8088: short
(specified by a signed 8 bit displacement) and long (specified by
a 16 bit displacement). Both are implemented in CHASM as a jump
to a label.
The short jump is specified by mnemonic JMPS, in accord with the
IBM disassembler, but not with The 8086 Book, which uses JMP.
Since one of the displacement bits is used to indicate direction,
only seven are left to express the magnitude of jump. JMPS (and
similarly, all the jump on condition instructions) is thus
limited to branching to labels within a range of -128 to +127
bytes.
CHASM reserves mnemonic JMP for the long jump. JMP may be used
to jump anywhere within the program segment, but the object code
generated is less compact than that from JMPS.
Examples:
START PROC NEAR
JMPS END ;short jump
JMP START ;long jump
END ENDP
21
D. Instruction Prefixes.
The 8088 supports three instruction prefixes:
1. SEG: segment override. An alternate segment register is
specified for a reference to memory
2. REP, REPE,REPNE,REPZ,REPNZ: repeat. A string primitive is
repeated until a condition is met.
3. LOCK: Turns on the LOCK signal. Only useful in
multi-processor situations.
CHASM implements these prefixes as separate instructions, rather
than prefixes to another instruction. They appear on a separate
line, immediately before the instruction which they modify.
Examples:
SEG ES
MOV AX,FLAG ;flag is in the extra segment
REP
MOVSB ;move bytes until CX decremented to 0
22
>>Pseudo-Operations<<
The following pseudo-ops are implemented:
A. BSAVE: Generate object code in BSAVE format.
Instructs CHASM to build a header in the format of BASIC's
BSAVE command. The resulting object code file may be BLOADed
by BASIC programs. No operands are required, and the
pseudo-op may appear anywhere within the source code.
Example:
ORG 0 ;no psp
SUBRT PROC FAR ;subroutine for BASIC program
BSAVE ;make BLOADable object file
B. COUNT ...ENDC: Count bytes.
Instructs CHASM to count the number of object code bytes
generated between COUNT and ENDC. Both machine instructions
and pseudo-ops can appear within the COUNT block. If a label
appears on the COUNT, it becomes an immediate operand of value
equal to the number of bytes counted. Neither COUNT or ENDC
require any operands. COUNTs cannot be nested.
It is *strongly* recommended that the immediate operands
generated by COUNT be accessed via the LENGTH function, which
unamgiuously forces the "immediate" type on CHASM's first
pass. If you do not use the LENGTH function, forward
references to a COUNT may cause phase errors. (See Phase
Error in the Error Message section.)
Example:
MESSAGE COUNT
MSG_TXT DB 'This utility requires DOS 2.0!' beep cr lf
ENDC
MOV SI, OFFSET(MSG_TXT)
MOV DI, OFFSET(BUFFER)
MOV CX, LENGTH(MESSAGE)
REP
MOVSB ;move message into buffer
23
C. DB: Declare Bytes
Memory locations are filled with values from the operand list.
Any number of operands may appear, but all must fit on one
line. Acceptable operands are immediate data, or strings
enclosed in single quotes ('). DB interprets strings as a
series of ASCII bytes.
If a label appears, it is redefined as a memory location, and
the data area may be referred to using the label, rather than
an address. Examples:
MOV AX,MASK
MASK DB 00H,01H
STG DB 'A string operand'
DB will attempt to interpret operands as byte values whenever
possible. For example, the operand 0012H results in only
*one* byte of object code being generated. However, since
OFFSET operands are always considered 16 bit quantities, two
bytes will be generated regardless of the OFFSET's magnitude.
==> Compiled version only.
The compiled version of CHASM generates an error message
("Data too large") if word operands (such as OFFSETs, or
numbers greater than 255) are found in the DB operand list.
DW should be used for declaring words in CHASM's compiled
version.
D. DM: Declare Multiple Bytes
==>Compiled version only.
Used to declare blocks of storage, the number of bytes
declared being the product of two immediate operands. If only
one operand is present, the other operand is assumed to equal
one.
24
As with DB, any label is redefined as a memory location. To
save space, the object code does not appear on the listing.
It is anticipated that this pseudo-op will be used in
conjunction with STRUC, to declare structured storage.
Example:
DM LENGTH(MAILIST) 500 ;mailing list with 500 entries
E. DS: Declare Storage
Used to declare large blocks of identically initialized
storage. The first operand is required, a number specifying
how many bytes are declared. If a second operand in the form
of a number 0-FFH appears, the locations will all be
initialized to this value. If the second operand is not
present, locations are initialized to 0. As with DB, any
label is redefined as a memory location. To save space, the
object code does not appear on the listing. Examples:
DS 10 ;10 locs initialized to 0
DS 100H,1AH ;256 locs initialized to 1AH
F. DW: Declare Words
==>Compiled version only.
Used to unambiguously assign a word of storage for each item
in the operand list. Any number of immediate operands may
appear, but all must fit on one line. As with DB, any label
is redefined as a memory location. Example:
DW 0012H, FFFFH ;four bytes declared
G. EJECT: Begin New Print Page
Causes CHASM to move to the top of the next page in printed
listings. Has no effect on listings sent to the screen or to
disk.
H. ENDC: End of Count
==> Compiled version only.
See COUNT (above) for details.
25
I. ENDP: End of Procedure
See PROC (below) for details.
J. ENDSTRUC: End of Structure
==>Compiled version only. See STRUC (below) for details.
K. EQU: Equate
Used to equate a symbolic name with a number. The symbol may
then be used anywhere the number would be used. Use of
symbols makes programs more understandable, and simplifies
modification.
An alternate form of EQU encloses the number in square
brackets: []. The symbol is then interpreted as a memory
location, and may be used as an address for memory access.
This version is provided to allow symbolic reference to
locations outside the program segment. Examples:
MOFFSET EQU 0B000H
MONOCHROME EQU [0000H]
Warning: Difficult to debug errors may result from using a
symbol prior to its being defined by EQU. I strongly urge
that all equates be grouped together at the beginning of
programs, before any other instructions. See "Phase Error" in
the Error Message section.
L. INCLUDE: Include file
==>Compiled version only.
INCLUDE requires one operand, a filename with optional drive
specifier and extension. The contents of the specified file
are logically inserted into the source file at the point
where the INCLUDE appears. INCLUDEs cannot be nested: an
error message will be printed if the specified file itself
contains an INCLUDE.
26
M. LIST: Enable listing output
==> Compiled version only.
Output to the list device is enabled, presumably after a
NOLIST was encountered. No operands required.
N. NOLIST: Disable listing output
==> Compiled version only.
Normal output to the list device is disabled. Error messages
are listed as usual. No operands required.
O. ORG: Origin
Allows direct manipulation of the location counter during
assembly. By default, CHASM assembles code to start at offset
100H, thus leaving room for the program segment prefix
normally built by COMMAND or DEBUG. In situations where no
PSP is provided, such as routines to be called from BASIC, you
should override this default with ORG, or incorrect assembly
may result.
ORG requires one operand, a number between 0 and 32767, which
represents the new setting of CHASM's location counter.
Although the location counter may be reset anywhere within a
program, generally this pseudo-op should be used before any
machine executable instructions for meaningful results.
Example:
ORG 0 ;Code will be assembled for starting
;offset of 0
27
P. PROC ...ENDP: Procedure Definition
Declares a procedure. One operand is required on PROC, either
the word NEAR, or the word FAR. This pseudo-op warns CHASM
whether to assemble returns as intra (near) or intersegment
(far). Procedures called from within your program should be
declared NEAR. All others should be FAR. ENDP terminates the
procedure, and requires no operands. If a RET is encountered
outside of a declared procedure, an error occurs. Procedures
may be nested, up to 10 deep. Example:
MAIN PROC FAR
...
... ;body of procedure
ENDP
Q. STRUC ...ENDSTRUC: Structure Definition
==> Compiled version only.
Declares a structure. STRUC requires no operands, and signals
CHASM that the following lines constitute a structure
template, and not actual storage declaration. If a label
appears on the STRUC, the label is equated with the length of
the structure.
ENDSTRUC terminates the structure definition, and requires no
operands.
Inside the structure, storage defining pseudo-ops behave
somewhat differently. See the section titled "Structures" for
more information. Example:
DIRENTRY STRUC ;disk directory entry
NAME DS 8
EXT DS 3
ATRIB DS 1
RESERVED DS 10
TIME DS 2
DATE DS 2
START DS 2
SIZE DS 4
ENDSTRUC
28
>>Structures<<
==>Compiled version only.
Structures are an advanced feature. Beginners may wish to skip
this section until they become more experienced with CHASM and
assembly language programming.
CHASM's structure capability allows you to generate a "template"
with which to organize repetitive data structures. As an example
of a repetitive data structure, consider a phone list. Each
entry in the list has three components:
Name - 20 characters
Address - 50 characters
Phone - 10 characters
Each entry thus uses a total of 80 bytes of storage. To declare
a list with 500 entries, you would declare 80 x 500 = 4000 bytes:
PHONELIST DS 4000 ;500 entries @ 80 bytes/entry
That's easy enough, but now what's the offset of the 346th
address field? This is starting to get confusing, and time
consuming to figure out.
Furthermore, hard-coding numbers (like that 4000, above) into a
program is never a good idea. What's going to happen when you
decide to add a zip code field, or make more room in the name
field because you just met Alexandria Zbrievskivich? You'd have
to go through and change by hand each number which depended on
the actual layout of your data. Murphy's law guarantees that
it'll take somewhere between "several" and "too many" assemblies
to find them all.
Structures allow you to set up a symbolic template which makes it
much easier to manage structured data like this phone list. By
using symbols defined in the structure, rather than bare numbers,
a change in data structure doesn't mean a frantic search
throughout your entire program to make corrections. If you
change the structure definition, the symbols take on new values
automatically.
29
Here's what the phone list structure looks like:
LISTENTRY STRUC
NAME DS 20
ADDRESS DS 50
PHONE DS 10
ENDSTRUC
Note the STRUC and ENDSTRUC statements. They mark the beginning
and end of the structure, and give it a name (LISTENTRY).
Within the structure are storage defining pseudo-ops. DS is used
in this example, but DB, DW, and DM could also be used. ORG can
be used within a structure, but any 8088 instruction will result
in an diagnostic message and termination of the structure
definition.
Inside a structure, the storage defining pseudo-ops
behave somewhat differently than normal. No actual storage is
set aside, but CHASM keeps track of how much space would normally
be declared.
Labels on pseudo-ops get assigned values equal to their offset
within the *structure*, not within the program as a whole. Also,
CHASM will treat the labels as immediate operands, rather than
memory locations. The result of the structure given above is to
generate three immediate operands, with the following values:
NAME = 0
ADDRESS = 20
PHONE = 70
CHASM does one other piece of useful book-keeping during
structure definitions. If a label appears on the STRUC
pseudo-op, it gets treated as an immediate operand, whose value
is equal to the total length of the structure.
You can either use the STRUC label directly as an operand, or if
you like "pretty" code, use the LENGTH operator on it. In this
example, both LISTENTRY and LENGTH(LISTENTRY) are immediate
operands of value 80.
(Inside note: LENGTH is a null operator, provided mainly for
aesthetic reasons. Using LENGTH will often make your code more
readable, but is equivalent to using just the label itself.)
30
Like equates, structures should be placed at the beginning of
your programs, before any machine instructions, otherwise phase
errors can occur. If you *do* embed structures inside your
program, you can eliminate any phase errors by using the LENGTH
function to reference any of the immmediate operands generated by
the embedded structure.
The immediate operands generated during a structure definition
can be very useful in writing your program. Following the phone
list example, here's a better way to declare storage for the
list, using the Declare Multiple pseudo-op:
PHONELIST DM LISTENTRY, 500 ;500 entries of length
;defined by the structure.
Now if you add another field to the structure, PHONELIST will
automatically increase in size.
The 8088's indirect addressing modes, coupled with structures,
make a very powerful combination for accessing structured data in
memory. Suppose AX contains the number of the entry you want to
work on. You can calculate the address of the entry as follows:
MOV BX, LENGTH(LISTENTRY) ;length per entry
MUL AX,BX ;times entry number
ADD AX, OFFSET(PHONELIST) ;plus the starting offset
MOV BX,AX ;BX <== frame pointer
BX is now a "frame pointer" - it points to the beginning of the
desired entry. You can access the various parts of the entry
using the optional displacement field in the indirect address.
For example, here's how you would store the letter 'A' into the
first byte of the address field:
MOV ADDRESS[BX], 'A'
As another example, the following line reads the first letter of
the name into the AL register:
MOV AL, NAME[BX]
31
The more complicated indirect modes can be used to scan through
or point within the fields. The following program fragment gets
the fourth digit in the phone number:
MOV DI, 4 ;specify 4th digit
MOV AL, PHONE[BX+DI] ;read it into AL
Often times, you'll want to process entries sequentially. To
move to the next entry, you just add the length of the entry to
the frame pointer:
ADD BX, LENGTH(LISTENTRY) ;point to next entry
The preceding examples should give you a feel for what you can
do with structures, but do not exhaust all the possibilities.
Experiment with this feature, and many of your programs will be
both more readable and more easily modified.
32
>>Outside the Program Segment<<
As mentioned previously, CHASM does not support multiple segment
definitions. Provision is made for limited access outside of the
program segment, however.
A. Memory References:
To access memory outside the program segment, you move a new
segment address into the DS register, then address using
offsets in the new segment. The memory option of the EQU
pseudo-op allows you to give a variable name to offsets in
other segments. For example, to access DOS's equipment flag:
BIOS_DATA EQU 40H
EQUIP_FLAG EQU [0010H]
MOV AX,BIOS_DATA ;can't move immed. to DS
MOV DS,AX
MOV AX,EQUIP_FLAG ;get bios equipment flag
B. Code Branching:
CHASM supports 4 instructions for branching outside the
program segment.
1. Direct CALL and JMP
New values for the PC and CS registers are included in the
instruction as two immediate operands. Example:
BIOS EQU 0F000H ;RAM bios segment
DISKETTE_IO EQU 0EC59H ;disk handler
JMP DISKETTE_IO,BIOS
2. Indirect CALLF and JMPF
Four consecutive bytes in memory are initialized with new
values for the PC and CS registers. The CALLF or JMPF then
references the address of the new values. Example:
BIOS EQU 0F000H ;RAM bios segment
PRINTER_IO EQU 0EFD2H ;printer routine
MOV [DI],PRINTER_IO
MOV 2[DI],BIOS
CALLF [DI]
33
>>Running CHASM<<
A. Prompt Mode
From DOS, type:
CHASM
After a few seconds, CHASM prints a hello screen, then
prompts:
Hit any key to continue...
CHASM will then prompt:
Source code file name? [.asm]
Type in the name of the file which contains your program. If
you do not include an extension for the filename, CHASM
assumes it to be .ASM. If CHASM is unable to find the file,
it will give you the option of naming another file, or
returning to DOS.
Assuming your file is present, CHASM prompts:
Direct listing to Printer (P), Screen (S), or Disk (D)?
[nul:]
Respond with either an upper or lower case letter. If you
just press enter, no listing will be produced. If you select
"D", CHASM will prompt:
Name for listing file? [fname.lst]
Type in a name for the listing file. If you just press ENTER,
the name defaults to that of your source file, with an
extension of .LST. Notes:
1. Error messages are always echoed to the screen.
2. Suppressing the listing will result in slightly faster
assembly.
34
The final prompt is:
Name for object file? [fname.com]
Type in a name for the assembled program. If you just press
ENTER, the name defaults to that of your source file, with an
extension of .COM.
CHASM now assembles your program. A status line is maintained
on the screen, showing how many lines have been processed.
CHASM makes two passes over your source file, outputting the
listing and object code on the second pass. You may abort
assembly and return to DOS at any time by pressing the Esc
key.
Please be patient during assembly, CHASM is written in BASIC,
and the interpreted version does a good imitation of a snail
crawling through molasses. An order form for a much faster
compiled version is included at the end of this document.
NOTE: I will send the Golden Bootstrap Award to the first
person submitting a complete implementation of CHASM,
rewritten in CHASM assembly language.
When finished, CHASM returns you to DOS, and you see the prompt:
A>
B. Expert Mode:
==>Compiled version only. This mode allows you to specify all
i/o information on the command line which invokes CHASM. The
syntax is:
CHASM sourcefile [p|s|d|/] [listfile|/] [objectfile]
Items within brackets ([]) are optional. You may select *one*
of any list of items separated by a bar (|).
Basically, you just include on the command line all your
responses to the normal prompts. Each response must be
separated from the others by either a space or comma.
35
If you don't specify the list device/file or the object file,
they default to NUL: and sourcename.COM respectively. To
represent a carriage return (to specify a default choice, but
allow modifying a later response) use the character slash
(/).
Expert mode examples:
1. Source file is CLEAR.ASM, no listing, object file
CLEAR.COM:
CHASM clear
2. Source file is SDIR.ASM, list to printer, object file
SDIR.COM:
CHASM sdir p
3. Source file is MYFILE.PRG, list to disk file MYFILE.LST,
object file SUBR.COM:
CHASM myfile.prg d / subr.com
36
>>Error and Diagnostic Messages<<
Error messages generated on pass one appear on the listing before
any source code is printed, and mention the line number to which
they refer. The majority of messages occur during pass two, and
will appear in the listing immediately prior to the line which
caused the message. Unless the listing itself is going to the
screen, messages and the source line which generated them will be
echoed there.
Add Leading Zero to Hex Constant: Diagnostic. The Undefined
Symbol could be interpreted as a hexadecimal number if a
leading zero was added.
Could Use JMPS: Diagnostic. The specified label requires an
offset of less than 128 bytes; specifying the short jump would
result in more compact code. The assembled code is correct,
however.
Data too Large: XXX XXX was found in DB operand list, but is a
word value. Use DW to declare words.
DM out of range: The product of the DM's operands is either
negative, or greater than 32767.
Duplicate Definition of XXX in (linenum): Pass 1 error. An
attempt was made to define a symbol already present in the
symbol table.
ENDC without COUNT: An ENDC was encountered, but no corresponding
COUNT was found.
ENDP without PROC: An ENDP was encountered, but no corresponding
PROC was found.
ENDSTRUC without STRUC: An ENDSTRUC was encountered, but no
corresponding STRUC was found.
EQU Without Label: No symbol was found to equate with the
operand.
File not found: XXX in (linenum). Pass one error. CHASM was
unable to find the file XXX, specified in the INCLUDE
pseudo-op.
37
Illegal Label: XXX in (linenum). Pass one error. The symbol XXX
begins in column one and has as its first character a number,
or a plus or minus sign.
Illegal Operation for Structure - ENDSTRUC Implied: Diagnostic.
The current line is within a structure, and is not a storage
defining pseudo-op. CHASM generates an ENDSTRUC, which
terminates the structure definition, then assembles the line
normally.
Illegal or Undefined Argument for LENGTH: The argument for the
LENGTH function was not present in the symbol table as an
immediate operand on pass 2.
Illegal or Undefined Argument for OFFSET: The argument for the
OFFSET function was not present in the symbol table as a near
label or memory location on pass 2.
Missing ENDC: The end of the input file was encountered, and at
least one COUNT had not been terminated by an ENDC.
Missing ENDP: The end of the input file was encountered, and at
least one PROC had not been terminated by an ENDP.
Missing ENDSTRUC: The end of the input file was encountered, and
at least one STRUC had not been terminated by an ENDSTRUC.
Nested COUNT: A COUNT was encountered while CHASM was already
COUNTing. COUNTs cannot be nested.
Nested INCLUDE: An INCLUDE was encountered in an INCLUDEd file.
The INCLUDE pseudo-op cannot be nested.
Nested Structure: A STRUC was encountered inside a structure.
Structures cannot be nested.
38
Phase Error: A label or memory location is found to have
different values on pass 1 and pass 2. A difficult to debug
error: generally the problem is not caused by the statement
which received the error message.
There are three documented ways to generate this error.
1. A previous instruction used a symbolic immediate operand
prior to the symbol's definition.
2. A previous instruction made improper use of a forward
referenced label, either an attempt to branch into a data
area, or to access a code area as if it was data.
3. The label on the flagged statement is defined more than
once in the program.
I would appreciate hearing about any other situations which
cause this message to appear.
Procedures Nested Too Deeply: Procedures may be nested no more
than 10 deep.
Source Line Truncated: The length of the input line exceeded 80
characters.
Specify Word or Byte Operation: Diagnostic. CHASM suggests that
the Syntax Error might be resolved by adding the suffix "B" or
"W" to the instruction mnemonic. Most, but not all, ambiguous
memory references are flagged with this diagnostic.
39
Syntax Error: (OP) (DTYPE) (STYPE). CHASM was unable to find a
version of the instruction (OP) which allows the operand types
(DTYPE) and (STYPE). Either the instruction doesn't exist, or
it is an inappropriate choice for the given operands. DTYPE
and STYPE are numbers which encode CHASM's guess as to what
the 1st and 2nd operands might be. The numbers are sums of the
types given in the following list:
1 = 8 bit accumulator 2 = 16 bit accumulator
4 = 8 bit register 8 = 16 bit register
16 = indirect memory reference 32 = CS register
64 = other segment register 128 = memory location
256 = immediate byte 512 = immediate word
1024 = none 2048 = string
4096 = near label 8192 = reserved
16384 = CL (count) register
Too Far For Short Jump: The displacement to the specified label
is not in the range -128 to +127.
Too Many User Symbols in (linenum): Pass one error. The symbol
table is full.
Undefined Operand for EQU: Any operands on an EQU statement must
have been previously defined.
Undefined Symbol XXX: The symbol XXX was used as an operand, but
never appeared as a label, and is not a predefined symbol.
Unrecognized Operand XXX: XXX is used in the DB or DW operand
list, but is not a valid immediate operand. (or string, in the
case of DB).
40
>>Execution of Assembled Programs<<
A. Object code format
The object code file produced by CHASM is in the form of a
memory image, exactly as will be present in your computer at
run time. No link step is required. Provided that the segment
registers are set correctly, the architecture of the 8088
guarantees that code is self-relocating, and will run correctly
loaded anywhere in memory. Storing a program as an exact image
of memory at run time is called the COM format by IBM.
This COM format is *not* that produced by the IBM assembler.
The output of the IBM assembler is in the form of an "object
module" suitable for input to the linker. To the best of my
knowledge, the object module is not directly executable, but
must first be "filtered" through the linker. This adds an
extra step to the process of producing a working program, but
gives you the option of combining multiple object modules into
one program. The resulting linked program is *still* not a
memory image, but has a header which is used to perform
relocation during loading. This linked program plus header is
called the EXE format by IBM.
B. Running Assembled Programs From DOS
DOS provides a loader for running machine language programs.
To run a program, you merely type its name, without the
extension. This is what you're doing every time you use a DOS
external command such as FORMAT or CHKDSK. In fact, the COM
format is named after "external COMmand".
When DOS loads a program, it examines the file extension to
determine what format the file is in, either COM or EXE. This
is why CHASM defaults to using the extension .com for your
object file. If you plan to run the program from DOS, don't
change the extension.
For COM programs, DOS builds a 255 byte long "program segment
prefix" and sets the segment registers to point to this PSP.
The contents of the file are then loaded verbatim right after
the PSP, at offset hex 100 in the segment defined by the
segment registers. As soon as loading is complete, your
program is executed starting with the instruction at hex 100.
41
Although you can totally ignore the PSP, you should read pages
E-3 through E-11 of the DOS manual to see what DOS puts there
for you. It turns out there are some real goodies which your
program might want to use.
When your program is done, it must transfer control back to
DOS, otherwise the 8088 will continue to fetch what it
believes are instructions from whatever garbage or bit-hash
happens to follow your program in memory. The easiest way to
return to DOS is to execute the instruction:
INT 20H
This is the vectored interrupt reserved by DOS for program
termination.
While we're on the topic of vectored interrupts, you would be
well rewarded to study both the DOS manual and Technical
Reference to find out what happens when you execute some of
the other interrupts. Some very useful functions, such as
file handling and screen i/o, are available at the machine
language level through this mechanism.
Looking at things the other way, by changing the interrupt
vector for a given function to point to your own code, you can
override the way DOS or the BIOS does something, and do it
your way. DOS even provides a method (via interrupt 27H) by
which your new code can be grafted onto DOS, and not be
overwritten by other programs.
C. Debugging Assembled Programs
IBM provides an excellent utility with DOS, called DEBUG.COM.
By specifying your program's name as a parameter when invoking
DEBUG, you can observe your program execute with DEBUG's trace
and other functions. To debug your program, from DOS type:
DEBUG progname.COM
DEBUG builds a PSP and loads your program just like DOS does,
but you have the added power of the debugging commands to
monitor your program while it runs. See chapter 6 of the DOS
manual for more details about using DEBUG.
42
On the topic of debugging, I can recommend most highly a
program called TRACE86, from Morgan Computing (10400 N.
Central Expressway, Suite 210, Dallas, TX 75231). The program
replaces DEBUG, and although a little steeply priced at $125,
makes the IBM debugger look silly. I've been using TRACE86
for some time now, and wouldn't be without it.
D. Using Assembled Programs in BASIC
To incorporate a machine language subroutine in a BASIC
program, write it in assembly language, then assemble it with
CHASM. You should read page C-7 of the BASIC manual for some
conventions to use in writing your subroutine. In particular,
note that you must declare the routine to CHASM as a FAR
procedure using the PROC pseudo-op, and that the last
instruction of the routine should be a RET.
Unlike programs which are run directly from DOS, your routine
will not be preceded by a program segment prefix. You should
prevent CHASM from leaving room for a PSP by putting an ORG 0
pseudo-op at the beginning of your routine. If you don't
include the ORG, memory references will not be assembled
correctly. Example:
ORG 0 ;no psp
SUBR PROC FAR ;far procedure
... ;body of subroutine
RET
ENDP
CHASM supports two methods for getting assembled routines into
BASIC programs. The methods differ in whether the routine is
included in the BASIC program file, or in a separate file.
To include the code within a BASIC program file, run it
through the utility COM2DATA, supplied on your CHASM disk.
COM2DATA reads in a .COM format file, and produces a file of
equivalent DATA statements which can be merged into a BASIC
program. Your program can then READ the data and POKE it into
memory. An example program to do this is given on page C-6 of
the BASIC manual. An alternative approach would be to store
the routine in a string variable, which could later be located
with the VARPTR function.
43
If you would prefer to keep your machine language subroutine
in a separate file, include a BSAVE pseudo-op somewhere within
your assembly language source code. CHASM will build a header
on the object code produced, which will mimic that built by
BASIC's BSAVE command. The resulting file may be BLOADed by
BASIC anywhere in memory.
You transfer control to your routine with either the USR
function, or the CALL statement. Syntax for these statements
can be found in the BASIC manual.
44
>>Notes for Those Upgrading to This Version of CHASM<<
CHASM is not yet carved in stone - improvements and corrections
are made fairly frequently, based on both my own experience in
using the program, and the comments of outside users. This
section summarizes the changes which have been made since version
1.2 was released. Changes followed with an asterisk (*) denote
modifications which could invalidate programs written under
earlier versions of CHASM.
Version Notes
3.14 Interpreted version frozen at version 2.13, further
changes apply only to compiled version. Memory
requirement raised to 128K. INCLUDE, STRUC,
ENDSTRUC, DM, DW, LIST, NOLIST, COUNT and ENDC
pseudo-ops added. Alternate mnemonics for the jump
on condition instructions, and alternate syntax for
the DIV and MUL instructions. Binary numbers added.
Intersegment CALL and JMP fixed.
2.13 Assembly can now be aborted with the Esc key.
Negative decimal numbers are working again. Input
lines now limited to 80 characters, and labels must
begin with a non-numeral. (*)
2.12 Listings can now be suppressed. Error messages are
echoed to the console on non-screen listings.
Expert mode added.
2.11 Pagination improved. Listings now time stamped.
OFFSETs and word values now allowed in DB operand
list.
2.10 Equated symbols allowed in the DB operand
list. Status line improved.
2.09 The first digit of hexadecimal constants must now be
in the range 0-9. A leading zero is permitted on four
digit hex constants, to allow fulfilling this
condition. (*)
2.08 Configuration process expanded. CHASM now skips over
perforations on printed listings. EJECT pseudo-op
added.
45
2.07 Oops. Configuration file now works as advertised.
2.06 CHASM now supports reverse long jumps.
2.05 Compiled version released. BSAVE pseudo-op.
Configuration process simplified.
2.04 TABs are now expanded and replaced with blanks, for
compatibility with IBM text editors.
2.03 Two bugs corrected. The first bug involved incorrect
assembly of indirect memory references which used a
displacement in the range 128-255. The second caused
a program crash if a hex number longer than 4 digits
was in found in the input file.
2.01 COM2DATA utility added.
2.00 Corrected a bug in the DS and DB pseudo-ops which
caused the last label in a program to be redefined as
a memory location. Also, the TAB character was added
as a new delimiter, and PRIMER.DOC was added to the
CHASM package.
1.9 The short jump is now represented with mnemonic JMPS,
for compatibility with DEBUG version 1.1. (*)
1.8 The operand type "character" was added as a new way
to represent immediate data.
1.7 The DS operator now works for blocks larger than 255
bytes. Also, the OFFSET function now works properly
in the displacement field of an indirect memory
reference.
1.6 A revision of this document. Some sections were
improved slightly, and in response to user requests,
a section on execution of assembled programs was
added.
1.5 Corrected an error which generated the message "Data
too Long" if the value FFH was used as 8 bit
immediate data.
46
1.4 User interface improved. CHASM now traps some common
input errors such as misspelling a file name, or
forgetting to turn on your printer.
1.3 A speed enhancement. Version 1.3 benchmarks about 5
times faster than version 1.2.
As can be seen, revisions are made on a regular basis. It is my
policy that after once contributing, users are entitled to all
future versions free of charge, with no further donation
expected. Contributing users are encouraged to send a disk and
return mailer from time to time, to receive the most current
version.
47
>>Miscellaneous and A Word From Our Sponsor...<<
A. System Requirements:
CHASM requires an 80 column display and at least one
disk drive. Memory requirements are as follows:
Interpreted version, DOS 1.1 ==> 64K
Interpreted version, DOS 2.0 ==> 96K
Compiled version, either DOS ==> 128K
B. Programming Notes:
1. CHASM is written in BASIC. The program is heavily
commented and very modular, so that if you'd like to see
how an assembler works, you should read the source listing.
CHASM's modular structure makes modification relatively
easy, if you'd like to customize. I'd like to hear about
any improvements people make, for possible inclusion in
future releases.
2. If you try to modify CHASM's interpreted version, there is
a quirk you should know about. Most of the initialization
code is in a "transient section" which is used once, then
deleted to make more room for the symbol table. Lines
50,000 - 65529 are reserved as this transient section.
Note Well: If you run CHASM, then save it to disk, you save
the program WITHOUT THE INITIALIZATION CODE. The resulting
program is non-functional. Be careful! Keep a backup.
3. CHASM.BAS will not compile directly to the EXE file
distributed as an upgrade. Contributors may request a copy
the compiled version's source code by sending a formatted
diskette and stamped, self-addressed return mailer. Do
*not* attempt to interpret this source file - it is not
suitable for input to the interpreter, and a system crash
may result if you try this. When compiling, use the /N and
/E options, to relax line numbering constraints and allow
error trapping.
48
C. Red Tape and Legal Nonsense:
1. Disclaimer:
CHASM is distributed as is, with no guarantee that it will
work correctly in all situations. In no event will the
Author be liable for any damages, including lost profits,
lost savings or other incidental or consequential damages
arising out of the use of or inability to use these
programs, even if the Author has been advised of the
possibility of such damages, or for any claim by any other
party.
Despite the somewhat imposing statement above, it *is* my
intention to fix any bugs which are brought to my
attention. Drop me a line if you think you've found a
problem.
2. Copyright Information:
The entire CHASM distribution package, consisting of the
main program, documentation files, and various data and
utility files, is copyright (c) 1983 and 1984 by David
Whitman. The author reserves the exclusive right to
distribute this package, or any part thereof, for profit.
The name "CHASM (tm)", applied to a microcomputer assembler
program, is a trade mark of David Whitman.
The package consisting of UNCOMPILED program source code
and the various subsidiary files may be copied freely by
individuals for evaluation purposes. It is expected that
those who find the package useful will make a contribution
directly to the author of the program.
THE AUTHOR RESERVES THE EXCLUSIVE RIGHT TO DISTRIBUTE OR
LICENSE DISTRIBUTION OF THIS PROGRAM IN COMPILED FORM.
UNAUTHORIZED DUPLICATION OF A COMPILED VERSION OF THIS
PROGRAM IS PUNISHABLE BY LAW.
Interested manufacturers are invited to contact Whitman
Software to discuss licensing CHASM for bundling with
MS-DOS based computer systems.
49
Distribution of CHASM outside the United States is through
licensed distributors, on a royalty basis. Interested
distributors are invited to contact Whitman Software.
3. Royalty Information:
No royalties are required to distribute programs produced
using CHASM. However, if you send me a copy of any major
program you have produced using CHASM, I'll give you a free
page of advertising in this document.
D. An Offer You Can't Refuse.
CHASM is distributed under a modification of the FREEWARE (tm)
marketing scheme, developed by Andrew Fluegelman, author of
PC-TALK, whose efforts are gratefully acknowledged.
Anyone may obtain a free copy of an interpreted version of the
program by sending a blank, formatted diskette to the author.
An addressed, postage-paid return mailer must accompany the
disk (no exceptions, please).
A copy of the program, with documentation, will be sent by
return mail. The program will carry a notice suggesting
a contribution to the program's author. Making a contribution
is totally voluntary on the part of the user. Regardless of
whether a contribution is made, the user is encouraged to
share the program with others. Payment for use is
discretionary on the part of each subsequent user.
The underlying philosophy here is based on three principles:
First, that the value and utility of software is best assessed by
the user on his/her own system. Only after using a program
can one really determine whether it serves personal
applications, needs, and tastes.
Second, that the creation of independent personal computer
software can and should be supported by those who benefit from
its use. Remember the Tanstaafl principal: There Ain't No
Such Thing as a Free Lunch.
50
Finally, that copying and networking of programs should be
encouraged, rather than restricted. The ease with which
software can be distributed outside traditional commercial
channels reflects the strength, rather than the weakness, of
electronic information.
If you like this software, please help support it. Your support
can take three forms:
1. A monatary contribution. $30 is suggested.
2. Suggestions, comments and bug reports. Your comments will
be taken seriously - user feedback was responsible for
most of the changes listed in CHASM's revision history.
3. Spread the word. Make copies of the interpreted version
for friends. Write the editor of your favorite computer
magazine. Advertizing costs are astronomical. To
continue offering CHASM this way, I need your help in
letting other people know about CHASM.
Those who make the $30 suggested payment receive the following
benefits:
1. User support, by phone or mail. I can only offer customer
support to those who are in fact *customers*. Phone
numbers and the address for support are given on the title
page of this manual.
2. A free upgrade to a compiled version of the program. The
compiled version executes much faster than the interpreted
and supports more features. An order form for the
compiled version is given at the end of this manual.
The compiled version is copyrighted, and users are requested NOT
to make copies other than for their own use. I am strongly
opposed to copy protection, and would regret being forced to
protect CHASM. Please recognize the amount of time and money
which went into producing CHASM, and respect the wishes of the
author.
David Whitman
136 Wellington Terrace
Lansdale, PA 19446
51
Appendix A: Mnemonic List
This appendix lists the mnemonics which CHASM will recognize,
grouped roughly by function. Consult "The 8086 Book" for
definitions of these instructions, and for the operands each will
accept. Mnemonics marked with an asterisk (*) will accept a 'B'
or 'W' suffix for ambiguous memory references. Those followed by
a "c" in parentheses (c) are only available in CHASM's compiled
version.
Arithmetic:
AAA AAD AAM AAS ADC* ADD* CBW
CWD CMP* CMPS* DAA DAS DEC* DIV*
IDIV* IMUL* INC* MUL* NEG* SBB* SUB*
Data Movement:
LAHF LDS LEA LES LODS* MOV* MOVS*
POP POPF PUSH PUSHF SAHF STOS* XCHG
XLAT
Logical:
AND* NOT* OR* TEST* XOR*
String Primitives:
CMPS* LODS* MOVS* SCAS* STOS*
Instruction Prefixes:
LOCK REP REPE REPNE REPNZ REPZ SEG
Program Counter Control: (unconditional)
CALL CALLN CALLF JMP JMPF JMPN JMPS
RET
52
Program Counter Control: (conditional)
JA JAE JB JBE JC JCXZ JE
JG JGE JL JLE JNA (c) JNAE (c) JNB (c)
JNBE (c) JNC JNE JNG (c) JNGE (c) JNL (c) JNLE (c)
JNO JNO JNP JNS JNZ JO JP
JPE JPO JS JZ LOOP LOOPE LOOPNE
LOOPNZ LOOPZ
Processor Control:
CLC CLD CLI CMC HLT NOP STC
STD STI WAIT
I/O:
IN OUT
Interrupt:
INT INTO IRET
Rotate and Shift:
RCL* RCR* ROL* ROR* SAL* SAR* SHL*
SHR*
53
Appendix B: Differences Between CHASM and That Other Assembler
Virtually all magazine articles about assembly language
programming on the IBM PC assume that the reader is using That
Other Assembler - you know, the one that costs $100. This
appendix will try to summarize the differences between the two
programs. Please note that I do not own a copy of That Other
Assembler, and therefore this section is not complete, nor even
guaranteed to be correct. Anyone with more experience is
invited to make additions or corrections.
A. General Differences
The biggest difference is philosophical. The IBM assembler was
designed for use by professional assembly language programmers,
to write operating systems and other huge projects. This is
reflected in the large size and relative complexity of the macro
assembler.
On the other hand, CHASM was designed for use by beginners, to
write relatively short programs. This was done by leaving out a
lot of the power offered by IBM's assembler, in exchange for
simplicity and small size. The main simplification involved
producing object code in the COM format, rather than the EXE
format chosen by IBM. There are two main consequences of this
choice:
1. You can't link routines assembled by CHASM to
compiled programs. (Although you *can* include them in
BASIC programs, interpreted or compiled.)
2. Your program has to fit in one 64K segment. If (shudder!)
you want to write a 256K assembly language program, you're
out of luck.
Like Pascal, the IBM assembler is a strongly typed language. By
requiring you to specify the *type* of each memory location you
will access in your program, the IBM assembler always knows what
size of memory operand you want. The disadvantage is a loss of
freedom: if you want to access only one byte of an area declared
as word, that's tough.
54
In analogy to the C language, CHASM is *not* strongly typed.
CHASM is perfectly happy extracting a byte from where you
originally set aside a word - CHASM can't tell the difference.
The consequence of this is that you have to *tell* CHASM
explicitly whether you want a byte or a word every time you
access memory. For any access to memory which doesn't have a
register as the other operand, you must add either a 'B' or a 'W'
to the instruction mnemonic used by IBM.
B. Miscellaneous Differences:
1. Short Jumps:
IBM uses the SHORT keyword, CHASM uses an 'S' suffix.
Example:
JMP SHORT label ;ibm
JMPS label ;chasm
2. Offset Function:
Where IBM precedes an operand with the keyword OFFSET,
CHASM has a *function* called OFFSET. CHASM requires
parentheses around the operand. Example:
MOV AX, OFFSET FCB ;ibm
MOV AX, OFFSET(FCB) ;chasm
3. Declaring Storage:
A. If you don't care what value a memory location is
initialized to, the IBM assembler allows you to specify
'?' as its contents. CHASM figures out how many bytes
you are declaring by how many values you give, so you
have to specify a starting value for every memory
location you declare. Example:
DB ? ;ibm
DB 0 ;chasm
55
B. The IBM assembler has a dizzying array of storage
defining pseudo-ops, in keeping with its strongly typed
philosophy. In practice, the only ones you'll likely
see are DB (declare byte) and DW (declare word). Users
of CHASM's interpreted version should declare two bytes
when you see DW in IBM syntax. The compiled version of
CHASM supports DW directly.
DW ? ;ibm
DB 00H, 00H ;interpreted chasm
DW 0000H ;compiled chasm
C. The IBM assembler allows the keyword DUP as an operand
in storage declaring pseudo-ops. This means to repeat
the definition as many times as the number just before
the DUP. Example:
DW 3 DUP(?) ;ibm
DB 0, 0 ;chasm
DB 0, 0 ; "
DB 0, 0 ; "
4. Expressions:
The IBM assembler allows you to perform arithmetic within the
operand list to calculate an address or immediate operand.
Thus, if you wanted the offset of the third byte after a
label, you could use "label + 3" as an operand. CHASM doesn't
support expression evaluation. The solution is to add labels
to any locations accessed via an expression, then use the
label directly. Example:
MOV AX, BUFFER + 3 ;ibm
BUFFER DB 4 DUP(?) ; "
MOV AX, BUFFER3 ;chasm
BUFFER DB 0, 0, 0 ; "
BUFFER3 DB 0 ; "
Sometimes a constant is given as an expression just to
emphasize its origin. For any such expressions which do not
involve a label, just substitute the numerical value of the
expression.
56
5. Segment Overrides:
The IBM assembler specifies a segment override as a prefix
attached to a memory operand. CHASM uses a separate
instruction, SEG, to override the default segment register for
the following instruction. Example:
XOR AL, ES:[DI] ;ibm
SEG ES ;chasm
XOR AL, [DI] ; "
6. ASSUME Pseudo-op:
IBM's ASSUME pseudo-op tells the assembler where the segment
registers will be pointing. CHASM always assumes that the CS,
DS and SS registers point to the beginning of the code
segment, and that the SS register has been set up to point to
a valid stack area. If you find an ASSUME pseudo-op where the
CS, DS and ES registers point to different locations, you will
have to figure out the addresses for memory references in the
DS or ES segments yourself.
7. Segment Pseudo-op:
This pseudo-op is used to set up multiple segments in the IBM
assembler. Since CHASM only allows one segment, there is no
equivalent pseudo-op. If there is only one segment definition
in an IBM assembler program, everything is fine, just leave
the pseudo-op out for CHASM.
Often times the SEGMENT pseudo-op is used to provide
addressing of an area in the BIOS, or perhaps the interrupt
vector table at the beginning of memory. For example, if a
program needed to get at the BIOS data area, in the IBM
assembler you would define a dummy segment with the same
structure as that in the BIOS listing in Technical Reference:
57
DATA SEGMENT AT 40H
RS232_BASE DW 4 DUP(?)
PRINTER_BASE DW 4 DUP(?)
EQUIP_FLAG DW ?
MFG_TST DB ?
MEMORY_SIZE DW ?
IO_RAM_SIZE DW ?
All this is really accomplishing is giving a name to some
memory locations which are outside the actual program being
written.
For CHASM, you'll have to figure out the actual addresses of
any of these data areas you want to use. In this case, you
can just look at the LOC column of the BIOS listing to get the
offset of each data area. For example, EQUIP_FLAG is at
offset 10H (check page A-2 of Tech. Ref). Given the
addresses, you can give CHASM names for each of the locations,
using the memory option of the EQU pseudo-op:
RS232_BASE EQU [00H]
PRINTER_BASE EQU [08H]
EQUIP_FLAG EQU [10H]
MFG_TEST EQU [12H]
MEMORY_SIZE EQU [13H]
IO_RAM_SIZE EQU [15H]
8. Labels:
The macro assembler indicates a local label by appending a
colon (:). The colon does not become part of the label, and
is not included when referencing the label. CHASM's labels
are all global, and although they may end with a colon, the
colon will become part of the label itself, and must then be
used when referencing the label. Example:
a2: mov ax,cx ;ibm
jmp a2 ; "
a2: mov ax,cx ;chasm
jmp a2: ; "
58
9. Entry Point:
The macro assembler allows you to specify the point within
your program where execution will begin. A label is put
on the entry point, then to indicate entry, the same label is
placed on the "END" pseudo-op. Since COM programs must always
start at offset 100H, CHASM doesn't allow setting an entry
point. (Also note that using the same label on two statements
is not allowed by CHASM.)
59
Appendix C: Description of Files
Your CHASM distribution disk contains a number of files. This
appendix will give a brief statement of the purpose of each.
Files marked with '*' will not appear on the standard
distribution disk, they are only available to contributors.
FILE DESCRIPTION
----------------------------------------------------------------
CHASM.BAS CHASM program, interpreted version.
CHASM.BAT Batch file to run CHASM.BAS from DOS.
CHASM.CFG Sample configuration file - for IBM printer
CHASM.DAT Data which tells CHASM how to assemble the
various 8088 mnemonics.
CHASM128.DAT * Expanded data for compiled version.
CHASM.DOC This document.
CHASM.EXE * CHASM program, compiled version.
CHASM.ZAP * Compiled version source code.
CLEAR.ASM Sample source file.
COM2DATA.BAS Utility for making BASIC subroutines.
COM2DATA.DOC Documentation for COM2DATA.
COM2DATA.EXE * Compiled version of COM2DATA.
COM2DATA.ASM * Source for DOS 2.0 filter version of COM2DATA.
FREEWARE.DOC References to other User Supported programs.
PRIMER.DOC Simple introduction to assembly language.
Occasionally, various other sample source files for CHASM will be
distributed. These files will have extension ASM, and will be
accompanied by a corresponding DOC file.
60
********COMPILED VERSION ORDER FORM********
Please copy CHASM version 3.14 onto the enclosed formatted
disk(s). I enclose a self-addressed, stamped mailer. I
understand that this compiled version of CHASM is copyrighted,
and agree not to distribute any unauthorized copies.
Diskette format: Total Memory: _______K
__ single sided
(128K required)
__ doubled sided
Disks may be formatted under either DOS 1.1 or 2.0
>> You must provide your own diskette and stamped, addressed
>> return mailer. Do NOT send money to cover these items!
Please check one:
__ I enclose a donation of $30 or more.
__ I have already made a donation. The enclosed check brings
my total contribution to $30 or more.
Where did you hear about CHASM? ________________________________
Name: _______________________________________________________
Address: _______________________________________________________
City, State, Zip: ______________________________________________
================================================================
Send order form, along with disk, return mailer and check to:
David Whitman
136 Wellington Terrace
Lansdale, PA 19446
Your order will be expedited if you mark your envelope:
"VERSION 3 UPGRADE"
===============================================================
61
==============PRINTER ENHANCEMENT===================
Michael Hoyt, of Soft and Friendly Software, has produced a set
of printer enhancement programs using CHASM, which is sold under
the name Prowriter Utilities. The package supports the following
printers:
NEC 8023A-C
Prowriter I (C. Itoh 8510)
Prowriter II (C. Itoh 1550)
The package contains three programs:
PRINT_CHARACTERS
PRINT_SCREEN
PRINT_SET
Once PRINT_CHARACTERS is run, it attaches itself to DOS, and
makes your printer have exactly the same character set as your
video monitor. The conversion is very professionally done.
Particularly impressive are the line drawing characters, which
actually form connected lines, both horizontally and vertically.
As if this wasn't enough, PRINT_CHARACTERS adds italics
capability as well. The italics make very effective emphasis in
documents and letters, and look really good.
PRINT_SCREEN is a graphics screen dump, activated by the normal
Shift/PrtSc sequence. Several options are available which trade
off speed and print quality. Since I have the mono card, I
haven't tried PRINT_SCREEN, but Michael sent me a sample printout
which looked quite nice.
PRINT_SET is a menu-driven program to turn on and off the various
special printing modes supported by these printers. A simple but
effective program.
I've been using this package with my NEC 8023 for a few months
now, and I like them quite a bit. To get a copy, send $35 to:
Soft and Friendly
RR 2 Box 65
Solsberry, IN 47459
62
================= NEW PRODUCT ==================
If you use the IBM/Microsoft BASIC compiler, chances are your
programs are bigger and slower than they have to be. If all
unreferenced line numbers are removed from your source program,
and the /N switch is used, BASCOM will "optimize" your program.
The result is tighter, more efficient code.
NUMZAP is a utility which carefully scans your source file, and
deletes all the non-essential line numbers. Performing this task
by hand would be prohibitively time consuming and you'd probably
introduce errors into your program in the process. NUMZAP will
do the job in minutes, 100% error free.
The CHASM source file was passed through NUMZAP, and the
resulting compiled code shrank by a factor of 10% (!). That
10% reduction could make the difference between your program
running in 64K, or having users with minimal systems get "Out of
Memory" messages just before your program crashes.
An added advantage to using NUMZAP is that bigger programs can be
compiled. You may not be aware that there is a limit on the size
of program which the compiler can handle. BASCOM uses up space
remembering the offset of each line number in your program. If
you have too many numbered lines, BASCOM will run out of room and
you'll get a unending series of "TC" (Too Complex) error
messages. By eliminating the unneeded line numbers, you give
BASCOM more elbow room. The free space available to compile
CHASM increased 27% (!) after using NUMZAP.
NUMZAP is available under the standard FREEWARE deal - just send
a formatted disk and self-addressed, stamped return mailer to:
David Whitman
136 Wellington Terrace
Lansdale, PA 19446
Be sure to specify that you are interested in NUMZAP. If you
like the program, a donation of $15 is suggested.